package podman

import (
	"context"
	"github.com/containers/podman/v5/pkg/bindings"
	"io"
	"net/http"
	"net/url"
	"strings"
)

type RequestBuilder struct {
	context     context.Context
	body        io.Reader
	method      string
	endpoint    string
	queryParams url.Values
	headers     http.Header
	pathValues  []string
}

func NewRequest(method, endpoint string) *RequestBuilder {
	return &RequestBuilder{
		method:      method,
		endpoint:    endpoint,
		queryParams: url.Values{},
		headers:     http.Header{},
	}
}

func (rb *RequestBuilder) WithContext(ctx context.Context) *RequestBuilder {
	rb.context = ctx
	return rb
}

func (rb *RequestBuilder) WithQuery(key, value string) *RequestBuilder {
	rb.queryParams.Set(key, value)
	return rb
}

func (rb *RequestBuilder) WithQueries(quires map[string]string) *RequestBuilder {
	for key, value := range quires {
		rb.queryParams.Set(key, value)
	}
	return rb
}

func (rb *RequestBuilder) WithHeader(key, value string) *RequestBuilder {
	rb.headers.Set(key, value)
	return rb
}

func (rb *RequestBuilder) WithHeaders(headers map[string]string) *RequestBuilder {
	for k, v := range headers {
		rb.headers.Set(k, v)
	}
	return rb
}

func (rb *RequestBuilder) WithBody(body io.Reader) *RequestBuilder {
	rb.body = body
	return rb
}

func (rb *RequestBuilder) WithPathValues(values ...string) *RequestBuilder {
	rb.pathValues = values
	return rb
}

func (rb *RequestBuilder) Build() (context.Context, io.Reader, string, string, url.Values, http.Header, []string) {
	return rb.context, rb.body, rb.method, rb.endpoint, rb.queryParams, rb.headers, rb.pathValues
}

func (rb *RequestBuilder) Send(conn *bindings.Connection) (*bindings.APIResponse, error) {
	return conn.DoRequest(rb.context, rb.body, rb.method, rb.endpoint, rb.queryParams, rb.headers, rb.pathValues...)
}

func NewGetRequest(endpoint string) *RequestBuilder {
	return NewRequest(http.MethodGet, endpoint)
}

func NewPostRequest(endpoint string) *RequestBuilder {
	return NewRequest(http.MethodPost, endpoint)
}

func (rb *RequestBuilder) WithHeaderContentType(contentType string) *RequestBuilder {
	rb.headers.Set("Content-Type", contentType)
	return rb
}

func (rb *RequestBuilder) WithHeaderAccept(accept ...string) *RequestBuilder {
	var filtered []string
	for _, a := range accept {
		if a != "" {
			filtered = append(filtered, a)
		}
	}
	if len(filtered) == 0 {
		return rb
	}

	rb.headers.Set("Accept", strings.Join(filtered, ", "))

	return rb
}

func (rb *RequestBuilder) WithHeaderAuthorization(auth string) *RequestBuilder {
	rb.headers.Set("Authorization", auth)
	return rb
}
